package com.lzx.adx.report.controller.v2;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.lzs.adx.commmon.utils.JsonUtils;
import com.lzs.adx.commmon.utils.Result;
import com.lzs.adx.commmon.utils.SpringContextUtils;
import com.lzx.adx.report.bean.mapper.ReportMapper;
import com.lzx.adx.report.cache.AccountLocalCache;
import com.lzx.adx.report.constant.ProductChannelConstant;
import com.lzx.adx.report.dto.AccountDTO;
import com.lzx.adx.report.dto.ReportDTO;
import com.lzx.adx.report.service.ReportService;
import com.lzx.adx.report.support.context.v2.CallBackV2Context;
import com.lzx.adx.report.support.context.v2.ReportV2Context;
import com.lzx.adx.report.support.strategy.v2.channel.AbstractReport;
import com.lzx.adx.report.support.strategy.v2.media.AbstractCallback;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class AbstractController<T> {


    public String reportBase(T t){
        ReportService reportService = SpringContextUtils.getBean(ReportService.class);
        ReportMapper reportMapper = SpringContextUtils.getBean(ReportMapper.class);
        ReportV2Context handlerReportContext = SpringContextUtils.getBean(ReportV2Context.class);
        ThreadPoolTaskExecutor reportExecutor = (ThreadPoolTaskExecutor) SpringContextUtils.getBean("reportExecutor");

        log.info("的请求参数为{}", JsonUtils.toJsonString(t));
        //1.收到监测的数据存储
        ReportDTO reportDTO = BeanUtil.copyProperties(t, ReportDTO.class);
        reportDTO.setType(1);
        reportDTO.setEventType(StringUtils.isBlank(reportDTO.getEventType())?"click":reportDTO.getEventType());
        reportDTO.setBizRequestId(IdUtil.fastSimpleUUID()+reportDTO.getDspId());
        reportDTO.setCreateTime(new Date());
        reportDTO.setUpdateTime(new Date());
        reportDTO.setExtend(JsonUtils.toJsonString(t));
        reportDTO.setTraceTime(String.valueOf(System.currentTimeMillis()/1000));
        reportExecutor.execute(()->{
            reportService.saveData(reportDTO);
        });

        AccountDTO accountDTO = AccountLocalCache.getInstance().get(reportDTO.getDspId());
        //不需要请求产品端的产品
        if(ProductChannelConstant.productChannelList.contains(accountDTO.getProductChannel())){
            log.info("账户ID{},无需上报给产品",reportDTO.getDspId());
            return "success";
        }

        AbstractReport abstractReport= handlerReportContext.getReport(accountDTO.getProductChannel());
        String result = abstractReport.report(reportDTO, accountDTO);
        return result;
    }


    public ResponseEntity baseCallback(Map<String,String> allParams) throws Exception {
        ReportService reportService = SpringContextUtils.getBean(ReportService.class);
        CallBackV2Context handlerCallBackContext = SpringContextUtils.getBean(CallBackV2Context.class);
        ThreadPoolTaskExecutor callBackExecutor = (ThreadPoolTaskExecutor) SpringContextUtils.getBean("callBackExecutor");

        String time = String.valueOf(System.currentTimeMillis());
        log.info("收到了回掉结果，请求的参数为{}",JSONObject.toJSONString(allParams));
        if (CollectionUtil.isEmpty(allParams)) {
            log.info("收到了回掉结果回调信息参数异常");
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
        // 获取当前线程的MDC上下文
        Map<String, String> contextMap = MDC.getCopyOfContextMap();

        //2.从缓存加载配置
        callBackExecutor.execute(()->{
            // 在子线程中设置MDC上下文
            if (contextMap != null) {
                MDC.setContextMap(contextMap);
            }
            handerCallBack(allParams, reportService, handlerCallBackContext, time);
            // 清除子线程的MDC上下文
            MDC.clear();
        });

        return ResponseEntity.ok(new Result());
    }


    /**
     * 处理回掉的相关业务
     * @param allParams
     * @param reportService
     * @param handlerCallBackContext
     * @param time
     */
    private static void handerCallBack(Map<String, String> allParams, ReportService reportService, CallBackV2Context handlerCallBackContext, String time) {
        String requestId = allParams.get("requestId");
        if(StringUtils.isBlank(requestId)){
            requestId= allParams.get("clickId");
        }

        //1.把转换结果更新到数据库
        Map<String, Object> params = new HashMap<>();
        params.put("bizRequestId", requestId);
        List<ReportDTO> list = reportService.list(params);
        ReportDTO reportDTO;
        if (CollectionUtil.isNotEmpty(list)) {
            reportDTO = list.get(0);
            log.info("账号{},收到了回传，回掉的结果为{}",reportDTO.getDspId(),JSONObject.toJSONString(allParams));
        } else {
            log.error("当前流水号{}，系统当前不存在",requestId);
            return;
        }

        AccountDTO accountDTO = AccountLocalCache.getInstance().get(reportDTO.getDspId());
        String dspExtend = accountDTO.getDspExtend();
        JSONObject jsonObject = JSONObject.parseObject(dspExtend);
        String callCode= jsonObject.getString("eventType");
        String eventTypeResult;
        //未配置转化字段，设置默认值
        if(StringUtils.isBlank(callCode)){
            eventTypeResult=jsonObject.getString("defaultType");
        }else{
            eventTypeResult = allParams.get(callCode);
            //如果配置了转化类型，但是值为空，看有没有设置默认值
            if(StringUtils.isBlank(eventTypeResult)){
                eventTypeResult=jsonObject.getString("defaultType");
            }
        }
        AbstractCallback abstractReport = handlerCallBackContext.getCallBack(accountDTO.getMediaChannel());
        abstractReport.callback(reportDTO, accountDTO, eventTypeResult, time);
    }
}
